﻿#pragma once
#include <windows.h>
#include <iostream>
#include <vector>
#include <map>
#include <QMutex>
#include "NtfsStructs.h"
#include "Drive.h"
#include "CommonDef.h"

#define SECTOR_SIZE 512 // 扇区大小（单位：字节）
#define MFTITEM_SIZE 1024 //一个MFT项大小（单位：字节）
#define ATTRIBUTE_NAME_SIZE 8 //索引名称大小（单位：字节）
#define FILENAME_MAX_LEN 255 //文件名最大长度
const std::map<uint32_t, bool> CONST_mapAttriList = { {0x20,1} ,{0x90,1} ,{0xA0,1}};
typedef struct _MFTFileArriList
{
	NtfsFile m_file;
	std::vector<AttrListItem> m_vec20AttriList;
	std::vector<std::pair<uint64_t, uint32_t>> m_vec80Runlist;
	std::pair<char *, uint64_t> m_80AttriData;
	std::vector<NtfsFile*> m_vec90FileList;
	std::vector<std::pair<uint64_t, uint32_t>> m_vecA0Runlist;
} MFTFileArriList;

class NtfsParse
{
public:
	NtfsParse(NtfsDrive *_parent);
	~NtfsParse() = default;
	int ReadDrive(const std::wstring &_wstrDrivePath, NtfsDrive &_hDrive);
	int ParseFile(uint64_t _uMFTNo, std::vector<File*>& _vecFileList, bool _blReparse = false);
	int ReparseFile(uint64_t _uMFTNo, std::vector<File*>& _vecFileList);
	int GetFileName(uint64_t _uMFTNo, NtfsFile& _file);
	int ParseMFT(uint64_t _uMFTNo, NtfsFile& _file, \
		std::vector<AttrListItem>& _vec20AttriList, \
		std::vector<std::pair<uint64_t, uint32_t>>& _vec80Runlist, \
		std::pair<char *, uint64_t> &_80fileData, \
		std::vector<NtfsFile*>& _vec90FileList, \
		std::vector<std::pair<uint64_t, uint32_t>>& _vecA0Runlist, const std::map<uint32_t, bool> &_mapFilter = CONST_mapAttriList);
	int ParseIndex(uint64_t _uClusterNo, uint64_t _uClusterSize, std::vector<NtfsFile*>& _vecFiles);
	int ParseData(uint64_t _uClusterNo, uint64_t _uClusterSize, char *_pBuf, LONGLONG _uSize, CopyFileData *_pCopyData);
	int GetFileData(uint64_t _uFtsNo, std::vector<std::pair<uint64_t, char *>> &_vecDataList);
	int BuildDriveIndex();
	int ParseMFTByFilter(MFTFileArriList &_parseResult, const std::map<uint32_t, bool> &_mapFilter = CONST_mapAttriList);
	bool ReadMFT(const char *_cpOffset, FastFileIndex &_fastIndex);

	void CopyFileById(CopyFileData *_pCopyData);

private:
	//打开分区表
	int OpenDrive(const std::wstring &_wstrDrivePath, NtfsDrive &_hDrive);
	//获取Boot信息
	int GetBoot(NtfsDrive &_drive);
	//获取MFT偏移
	int GetMFTOffset(NtfsDrive &_drive);
	
	uint32_t Parse10H(char* _pBuf, uint64_t _uMFTNo, NtfsFile& _file, bool _blIsGoto = false);
	uint32_t Parse20H(char* _pBuf, uint64_t _uMFTNo, std::vector<AttrListItem>& _vec20AttriList, bool _blIsGoto = false);
	uint32_t Parse30H(char* _pBuf, uint64_t _uMFTNo, NtfsFile& _file, bool _blIsGoto = false);
	uint32_t Parse40H(char* _pBuf, uint64_t _uMFTNo, bool _blIsGoto = false);
	uint32_t Parse50H(char* _pBuf, uint64_t _uMFTNo, bool _blIsGoto = false);
	uint32_t Parse60H(char* _pBuf, uint64_t _uMFTNo, bool _blIsGoto = false);
	uint32_t Parse70H(char* _pBuf, uint64_t _uMFTNo, bool _blIsGoto = false);
	uint32_t Parse80H(char* _pBuf, uint64_t _uMFTNo, std::vector<std::pair<uint64_t, uint32_t>>& _vec80Runlist, std::pair<char *, uint64_t> &_fileData, bool _blIsGoto = false);
	uint32_t Parse90H(char* _pBuf, uint64_t _uMFTNo, std::vector<NtfsFile*>& _vec90FileList, bool _blIsGoto = false);
	uint32_t ParseA0H(char* _pBuf, uint64_t _uMFTNo, std::vector<std::pair<uint64_t, uint32_t>> &_vecRunlist, bool _blIsGoto = false);
	uint32_t ParseB0H(char* _pBuf, uint64_t _uMFTNo, bool _blIsGoto = false);
	uint32_t ParseC0H(char* _pBuf, uint64_t _uMFTNo, bool _blIsGoto = false);
	uint32_t ParseD0H(char* _pBuf, uint64_t _uMFTNo, bool _blIsGoto = false);
	uint32_t ParseE0H(char* _pBuf, uint64_t _uMFTNo, bool _blIsGoto = false);
	uint32_t Parse100H(char* _pBuf, uint64_t _uMFTNo, bool _blIsGoto = false);

	//解析datarun
	void ParseDataRun(char *_pBuf, std::vector<std::pair<uint64_t, uint32_t>> &_vecRunlist);

	//判断是否为负数，为负则返补码
	int64_t CalcOffset(char *_pBuf, int _iSize);

	//解析索引项
	void ParseIndexItem(char *_pBuf, uint32_t _iSize, std::vector<NtfsFile*>& _vecFiles);

	void GetStandardInfo(PStandardInfoAttrBody _pAttr, NtfsFile& _file);
	int GetFileNameInfo(PFileNameAttrBody _pAttr, NtfsFile& _file);
	bool IsPesidentAttr(const char* _pBuf);


private:
	NtfsDrive* m_pParent = nullptr;
	QMutex m_lock;
};


